﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using OAuthProtocol;
using System.Net;
using System.IO;
using System.Web;

namespace OAuthProtocol
{
    public class OAuth
    {
        private readonly OAuthBase r_oAuthBase;

        public OAuth()
        {
            r_oAuthBase = new OAuthBase();
        }

        public OAuthToken GetRequestToken(Uri baseUri, string consumerKey, string consumerSecret)
        {
            var uri = new Uri(baseUri, "oauth/request_token");

            uri = SignRequest(uri, consumerKey, consumerSecret);

            var request = (HttpWebRequest)WebRequest.Create(uri);
            request.Method = WebRequestMethods.Http.Get;

            var response = request.GetResponse();

            var queryString = new StreamReader(response.GetResponseStream()).ReadToEnd();

            var parts = queryString.Split('&');
            var token = parts[1].Substring(parts[1].IndexOf('=') + 1);
            var secret = parts[0].Substring(parts[0].IndexOf('=') + 1);

            return new OAuthToken(token, secret);
        }

        public Uri GetAuthorizeUri(Uri baseUri, OAuthToken requestToken)
        {
            var queryString = String.Format("oauth_token={0}", requestToken.Token);
            var authorizeUri = String.Format("{0}{1}?{2}", baseUri, "oauth/authorize", queryString);
            return new Uri(authorizeUri);
        }



        public OAuthToken GetAccessToken(Uri baseUri, string consumerKey, string consumerSecret, OAuthToken requestToken)
        {
            var uri = new Uri(baseUri, "oauth/access_token");

            uri = SignRequest(uri, consumerKey, consumerSecret, requestToken);

            var request = (HttpWebRequest)WebRequest.Create(uri);
            request.Method = WebRequestMethods.Http.Get;

            var response = request.GetResponse();
            var reader = new StreamReader(response.GetResponseStream());
            var accessToken = reader.ReadToEnd();

            var parts = accessToken.Split('&');
            var token = parts[1].Substring(parts[1].IndexOf('=') + 1);
            var secret = parts[0].Substring(parts[0].IndexOf('=') + 1);

            return new OAuthToken(token, secret);
        }


        public Uri SignRequest(Uri i_uri, string i_consumerKey, string i_consumerSecret, OAuthToken i_token, string i_httpMethod)
        {
            var nonce = r_oAuthBase.GenerateNonce();
            var timestamp = r_oAuthBase.GenerateTimeStamp();
            string parameters;
            string normalizedUrl;

            string requestToken = i_token == null ? String.Empty : i_token.Token;
            string tokenSecret = i_token == null ? String.Empty : i_token.Secret;

            var signature = r_oAuthBase.GenerateSignature(
                i_uri, i_consumerKey, i_consumerSecret,
                requestToken, tokenSecret, i_httpMethod, timestamp,
                nonce, OAuthBase.SignatureTypes.HMACSHA1,
                out normalizedUrl, out parameters);

            var requestUri = String.Format("{0}?{1}&oauth_signature={2}",
                normalizedUrl, parameters, WebUtility.UrlEncode(signature));

            return new Uri(requestUri);
        }

        public Uri SignRequest(Uri uri, string consumerKey, string consumerSecret, OAuthToken token = null)
        {
            return SignRequest(uri, consumerKey, consumerSecret, token, "GET");
        }
    }
}
